from django.conf import settings
from django.db.models import Avg, Sum, Count, Max, Min, Q, F

import django_filters
from django_filters.rest_framework import DjangoFilterBackend, FilterSet

from rest_framework import serializers
from rest_framework.serializers import *
from rest_framework.validators import UniqueValidator, UniqueTogetherValidator  # 验证器

# from allinpay import apidev as PAY
# from iClouds.apidev import py_str
from mysqldb.models import *
from mysqldb import redis as REDIS


class AllinpayQueryInListFilterSet(FilterSet):
    """收单筛选器"""

    # uid = django_filters.NumberFilter(
    #     field_name="pid", method="filter_uid", label="用户ID"
    # )
    pid = django_filters.NumberFilter(field_name="pid", label="场所ID")
    tid = django_filters.NumberFilter(field_name="tid", label="名目ID")
    strdate = django_filters.DateFilter(
        field_name="trxdate", required=False, method="filter_strdate", label="开始日期"
    )
    enddate = django_filters.DateFilter(
        field_name="trxdate", required=False, method="filter_enddate", label="结束日期"
    )

    # def filter_uid(self, qs, name, value):
    #     pid = []
    #     [
    #         pid.append(p[0])
    #         for p in AllinpayUserplaceList.objects.filter(uid=value).values_list("pid")
    #     ]
    #     lookup = "__".join([name, "in"])
    #     return qs.filter(**{lookup: pid})

    def filter_strdate(self, qs, name, value):
        value = str(value).replace("-", "").replace("/", "")
        lookup = "__".join([name, "gte"])
        return qs.filter(**{lookup: value})

    def filter_enddate(self, qs, name, value):
        value = str(value).replace("-", "").replace("/", "")
        lookup = "__".join([name, "lte"])
        return qs.filter(**{lookup: value})

    class Meta:
        model = AllinpayReceiptList
        fields = ["pid", "tid", "strdate", "enddate"]


class AllinpayQueryOutListFilterSet(FilterSet):
    """退单筛选器"""

    # uid = django_filters.NumberFilter(field_name="oldreqsn", method="filter_uid")
    pid = django_filters.NumberFilter(field_name="pid", label="场所ID")
    tid = django_filters.NumberFilter(field_name="tid", label="名目ID")
    strdate = django_filters.DateFilter(
        field_name="fintime", required=False, method="filter_strdate", label="开始日期"
    )
    enddate = django_filters.DateFilter(
        field_name="fintime", required=False, method="filter_enddate", label="结束日期"
    )

    # def filter_uid(self, qs, name, value):
    #     pid, dan = [], []
    #     [
    #         pid.append(p[0])
    #         for p in AllinpayUserplaceList.objects.filter(uid=value).values_list("pid")
    #     ]
    #     [
    #         dan.append(d[0])
    #         for d in AllinpayReceiptList.objects.filter(pid__in=pid).values_list(
    #             "cusorderid"
    #         )
    #     ]
    #     lookup = "__".join([name, "in"])
    #     return qs.filter(**{lookup: dan})

    # def filter_pid(self, qs, name, value):
    #     dan = []
    #     [
    #         dan.append(d[0])
    #         for d in AllinpayReceiptList.objects.filter(pid=value).values_list(
    #             "cusorderid"
    #         )
    #     ]
    #     lookup = "__".join([name, "in"])
    #     return qs.filter(**{lookup: dan})

    # def filter_tid(self, qs, name, value):
    #     dan = []
    #     [
    #         dan.append(d[0])
    #         for d in AllinpayReceiptList.objects.filter(tid=value).values_list(
    #             "cusorderid"
    #         )
    #     ]
    #     lookup = "__".join([name, "in"])
    #     return qs.filter(**{lookup: dan})

    def filter_strdate(self, qs, name, value):
        value = str(value).replace("-", "").replace("/", "")
        value += "000000"
        lookup = "__".join([name, "gte"])
        return qs.filter(**{lookup: value})

    def filter_enddate(self, qs, name, value):
        value = str(value).replace("-", "").replace("/", "")
        value += "235959"
        lookup = "__".join([name, "lte"])
        return qs.filter(**{lookup: value})

    class Meta:
        model = AllinpayCancelList
        fields = ["pid", "tid", "strdate", "enddate"]


class AllinpaySettleListFilterSet(FilterSet):
    """结算筛选器"""

    # uid = django_filters.NumberFilter(
    #     field_name="pid", method="filter_uid", label="用户ID"
    # )
    pid = django_filters.NumberFilter(field_name="pid", label="场所ID")
    tid = django_filters.NumberFilter(field_name="tid", label="名目ID")
    strdate = django_filters.DateFilter(
        field_name="trxdate", required=False, method="filter_strdate", label="开始日期"
    )
    enddate = django_filters.DateFilter(
        field_name="trxdate", required=False, method="filter_enddate", label="结束日期"
    )

    # def filter_uid(self, qs, name, value):
    #     pid = []
    #     [
    #         pid.append(p[0])
    #         for p in AllinpayUserplaceList.objects.filter(uid=value).values_list("pid")
    #     ]
    #     lookup = "__".join([name, "in"])
    #     return qs.filter(**{lookup: pid})

    def filter_strdate(self, qs, name, value):
        value = str(value).replace("-", "").replace("/", "")
        lookup = "__".join([name, "gte"])
        return qs.filter(**{lookup: value})

    def filter_enddate(self, qs, name, value):
        value = str(value).replace("-", "").replace("/", "")
        lookup = "__".join([name, "lte"])
        return qs.filter(**{lookup: value})

    class Meta:
        model = AllinpaySettlementList
        fields = ["pid", "tid", "strdate", "enddate"]


class NoneSerializer(serializers.Serializer):
    """无序列化"""

    class Meta:
        fields = "__all__"


class PaycodeSerializer(serializers.Serializer):
    """扫码页面接口"""

    reqsn = CharField(help_text="商户交易单号")

    def validate_reqsn(self, attr):
        attr = attr.upper()
        if not REDIS.redis_exis("allinpay", attr):
            raise serializers.ValidationError("未找到交易单号")
        return attr


class ActivePaySerializer(serializers.Serializer):
    """用户主扫收款"""

    pid = IntegerField(help_text="场所ID")
    tid = IntegerField(help_text="经营名目ID")
    reqsn = CharField(help_text="商户交易单号,保证商户平台唯一")
    trxamt = IntegerField(min_value=1, help_text="交易金额,单位为分")
    paytype = ChoiceField(["W01", "A01"], required=True, help_text="交易方式")
    # placeid = IntegerField(required=True, help_text="门店场所ID")
    # termsn = IntegerField(required=True, help_text="经营名目ID")
    # chnlstoreid = IntegerField(required=True, help_text="门店场所ID")
    # operatorid = IntegerField(required=True, help_text="经营名目ID")

    def validate_reqsn(self, attr):
        attr = attr.upper()
        if REDIS.redis_exis("bankreqsn", attr):
            raise serializers.ValidationError("该订单已存在")
        if AllinpayOrderList.objects.filter(reqsn=attr).count():
            raise serializers.ValidationError("该订单已过期")
        return attr

    def validate_pid(self, attr):
        try:
            place = AllinpayPlaceList.objects.get(id=attr, status__gt=0)
        except BaseException as err:
            raise serializers.ValidationError("未找到有效的经营场所")
        return attr

    def validate(self, attrs):
        try:
            bind = AllinpayTermList.objects.get(id=attrs["tid"], status__gt=0)
        except BaseException as err:
            raise serializers.ValidationError({"tid": "未找到经营名目"})
        if not bind.pid == attrs["pid"]:
            raise serializers.ValidationError({"tid": "该场所未找到经营名目"})
        return attrs


class SweptPaySerializer(serializers.Serializer):
    """用户被扫收款"""

    pid = IntegerField(help_text="场所ID")
    tid = IntegerField(help_text="经营名目ID")
    reqsn = CharField(max_length=32, help_text="商户交易单号,保证商户平台唯一")
    trxamt = IntegerField(min_value=1, help_text="交易金额,单位为分")
    authcode = CharField(max_length=32, help_text="付款码")
    # placeid = IntegerField(help_text="门店号")
    # termsn = IntegerField(help_text="终端序列号")
    # chnlstoreid = IntegerField(required=True, help_text="门店场所ID")
    # operatorid = IntegerField(required=True, help_text="经营名目ID")

    def validate_reqsn(self, attr):
        attr = attr.upper()
        if REDIS.redis_exis("bankreqsn", attr):
            raise serializers.ValidationError("该订单已存在")
        if AllinpayOrderList.objects.filter(reqsn=attr).count():
            raise serializers.ValidationError("该订单已过期")
        return attr

    def validate_pid(self, attr):
        try:
            place = AllinpayPlaceList.objects.get(id=attr, status__gt=0)
        except BaseException as err:
            raise serializers.ValidationError("未找到有效的经营场所")
        return attr

    def validate(self, attrs):
        try:
            bind = AllinpayTermList.objects.get(id=attrs["tid"], status__gt=0)
        except BaseException as err:
            raise serializers.ValidationError({"tid": "未找到经营名目"})
        return attrs


class TransQuerySerializer(serializers.Serializer):
    """查询接口"""

    reqsn = serializers.CharField(required=False, help_text="商户交易单号")
    trxid = serializers.CharField(required=False, help_text="平台流水号")

    def validate_reqsn(self, attr):
        return attr.upper()

    def validate_trxid(self, attr):
        return attr.upper()

    def validate(self, attrs):
        attrs = dict(attrs)
        if not len(attrs) == 1:
            raise serializers.ValidationError({"transquery": "参数错误"})
        return attrs


class AlertSerializer(serializers.ModelSerializer):
    """消息通知接口"""

    id = IntegerField(label="ID", read_only=True)
    pid = IntegerField(read_only=True, help_text="场所ID")
    tid = IntegerField(read_only=True, help_text="终端ID")
    acct = CharField(required=False, help_text="交易账号")
    accttype = CharField(required=False, help_text="借贷标识")
    appid = CharField(required=False, help_text="APPID")
    chnltrxid = CharField(required=False, help_text="渠道流水号")
    cmid = CharField(required=False, help_text="渠道子商户号")
    cusid = CharField(required=False, help_text="商户编号")
    cusorderid = CharField(required=False, help_text="业务流水")
    fee = CharField(required=False, help_text="手续费")
    initamt = CharField(required=False, help_text="原始下单金额")
    outtrxid = CharField(required=False, help_text="第三方交易号")
    paytime = CharField(required=False, help_text="交易完成时间")
    termauthno = CharField(required=False, help_text="终端授权码")
    termrefnum = CharField(required=False, help_text="终端参考号")
    termtraceno = CharField(required=False, help_text="终端流水号")
    trxamt = CharField(required=False, help_text="交易金额")
    trxcode = CharField(required=False, help_text="交易类型")
    trxdate = CharField(required=False, help_text="交易请求日期")
    trxid = CharField(required=False, help_text="收银宝交易单号, 唯一")
    trxstatus = CharField(required=False, help_text="交易结果码")
    # name = SerializerMethodField(read_only=True)
    # term = SerializerMethodField(read_only=True)
    termno = CharField(required=False, help_text="终端号")
    termbatchid = CharField(required=False, help_text="终端批次号")
    trxreserved = CharField(required=False, help_text="原交易备注")
    srctrxid = CharField(required=False, help_text="原交易通联平台流水号")

    class Meta:
        model = AllinpayReceiptList
        fields = (
            "id",
            "pid",
            "tid",
            "acct",
            "accttype",
            "appid",
            "chnltrxid",
            "cmid",
            "cusid",
            "cusorderid",
            "fee",
            "initamt",
            "outtrxid",
            "paytime",
            "termauthno",
            "termrefnum",
            "termtraceno",
            "trxamt",
            "trxcode",
            "trxdate",
            "trxid",
            "trxstatus",
            # "name",
            # "term",
            # 差错调整通知差异字段
            "termno",
            "termbatchid",
            "trxreserved",
            "srctrxid",
        )
        # fields = "__all__"

    def get_name(self, attr):
        try:
            bind = AllinpayPlaceList.objects.get(id=attr.pid).name
            return bind
        except BaseException as err:
            return "未找到该场所"

    def get_term(self, attr):
        try:
            bind = AllinpayTermList.objects.get(id=attr.tid).name
            return bind
        except BaseException as err:
            return "未找到该经营名目"


class CancelOrderSerializer(serializers.Serializer):
    """撤销交易请求"""

    pid = IntegerField(help_text="场所ID")
    tid = IntegerField(help_text="经营名目ID")
    reqsn = CharField(max_length=32, help_text="商户交易单号")
    trxamt = IntegerField(min_value=1, help_text="原订单金额,单位为分")
    oldreqsn = CharField(help_text="原交易的商户交易单号")
    # oldtrxid = CharField(required=False, help_text="原交易的平台流水号")

    class Meta:
        fields = "__all__"

    def validate_reqsn(self, attr):
        attr = attr.upper()
        if REDIS.redis_exis("bankreqsn", attr):
            raise serializers.ValidationError("该订单已存在")
        if AllinpayOrderList.objects.filter(reqsn=attr).count():
            raise serializers.ValidationError("该订单已过期")
        return attr

    def validate_pid(self, attr):
        try:
            place = AllinpayPlaceList.objects.get(id=attr, status__gt=0)
        except BaseException as err:
            raise serializers.ValidationError("未找到有效的经营场，请检查场所状态")
        return attr

    def validate(self, attrs):
        try:
            bind = AllinpayTermList.objects.get(id=attrs["tid"], status__gt=0).auth
        except BaseException as err:
            raise serializers.ValidationError({"tid": "未找到经营名目"})
        if not bind == attrs["pid"]:
            raise serializers.ValidationError({"tid": "该场所未找到经营名目"})
        return attrs


class ReturnOrderSerializer(serializers.Serializer):
    """退款交易请求"""

    pid = IntegerField(help_text="场所ID")
    tid = IntegerField(help_text="经营名目ID")
    reqsn = CharField(help_text="商户交易单号")
    trxamt = IntegerField(min_value=1, help_text="退款金额,单位为分")
    oldreqsn = CharField(help_text="原交易的商户交易单号")
    # oldtrxid = CharField(required=False, help_text="原交易的平台流水号")

    class Meta:
        fields = "__all__"

    def validate_reqsn(self, attr):
        attr = attr.upper()
        if REDIS.redis_exis("bankreqsn", attr):
            raise serializers.ValidationError("该订单已存在")
        if AllinpayOrderList.objects.filter(reqsn=attr).count():
            raise serializers.ValidationError("该订单已过期")
        return attr

    def validate_pid(self, attr):
        try:
            place = AllinpayPlaceList.objects.get(id=attr, status__gt=0)
        except BaseException as err:
            raise serializers.ValidationError("未找到有效的经营场，请检查场所状态")
        return attr

    def validate(self, attrs):
        try:
            bind = AllinpayTermList.objects.get(id=attrs["tid"], status__gt=0).auth
        except BaseException as err:
            raise serializers.ValidationError({"tid": "未找到经营名目"})
        if not bind == attrs["pid"]:
            raise serializers.ValidationError({"tid": "该场所未找到经营名目"})
        return attrs


class AllOrderSerializer(serializers.ModelSerializer):
    """撤销和退款存储"""

    id = IntegerField(read_only=True)
    chnltrxid = CharField(required=False, help_text="渠道流水号")
    errmsg = CharField(required=False, help_text="错误原因")
    fee = CharField(required=False, help_text="手续费")
    fintime = CharField(required=False, help_text="交易完成时间")
    oldreqsn = CharField(required=False, help_text="原平台单号")
    oldtrxid = CharField(required=False, help_text="原收银宝交易流水号")
    reqsn = CharField(required=False, help_text="商户交易单号")
    trxid = CharField(
        required=False,
        help_text="收银宝交易单号, 唯一",
        validators=[UniqueValidator(queryset=AllinpayCancelList.objects.all())],
    )
    trxstatus = CharField(required=False, help_text="交易状态")
    trxcode = CharField(required=False, help_text="交易类型")
    trxamt = CharField(required=False, help_text="交易金额(分)")
    pid = IntegerField(required=False, help_text="场所ID")
    tid = IntegerField(required=False, help_text="经营名目")

    class Meta:
        model = AllinpayCancelList
        fields = "__all__"


class SettlementPostSerializer(serializers.Serializer):
    """结算请求"""

    pid = IntegerField(required=False, help_text="场所ID")
    tid = IntegerField(required=False, help_text="经营名目ID")
    bind = SerializerMethodField(read_only=True)

    class Meta:
        fields = ("pid", "tid")

    def get_bind(self, attrs):
        tids = []
        # 创建结算对象列表
        if "tid" in attrs.keys() and "pid" in attrs.keys():
            """结算一组"""
            try:
                place = AllinpayPlaceList.objects.get(id=attrs["pid"])
            except BaseException as err:
                raise serializers.ValidationError("场所不存在")
            try:
                term = AllinpayTermList.objects.get(id=attrs["tid"])
            except BaseException as err:
                raise serializers.ValidationError("名目不存在")
            tids.append([place.id, term.id, place.fee])
        elif "tid" in attrs.keys():
            """结算一组"""
            try:
                term = AllinpayTermList.objects.get(id=attrs["tid"])
            except BaseException as err:
                raise serializers.ValidationError("名目不存在")
            try:
                place = AllinpayPlaceList.objects.get(id=term.auth)
            except BaseException as err:
                raise serializers.ValidationError("场所不存在")
            tids.append([place.id, term.id, place.fee])
        elif "pid" in attrs.keys():
            """结算一家"""
            try:
                place = AllinpayPlaceList.objects.get(id=attrs["pid"])
            except BaseException as err:
                raise serializers.ValidationError("场所不存在")
            terms = AllinpayTermList.objects.filter(auth=attrs["pid"]).values_list(
                "id", flat=True
            )
            for i in terms:
                tids.append([place.id, i, place.fee])
        else:
            """结算全部"""
            place = AllinpayPlaceList.objects.all().values_list("id", "fee")
            for i in place:
                terms = AllinpayTermList.objects.filter(auth=i[0]).values_list(
                    "id", flat=True
                )
                for j in terms:
                    tids.append([i[0], j, i[1]])
        # 上次结算日期
        for i in range(len(tids)):
            try:
                trxdate = (
                    AllinpaySettlementList.objects.filter(
                        pid=tids[i][0], tid=tids[i][1]
                    )
                    .last()
                    .trxdate
                )
            except BaseException as err:
                trxdate = None
            tids[i].append(trxdate)
        return tids


class AllinpaySettlementAutoSerializer(serializers.ModelSerializer):
    """创建结算表记录"""

    id = IntegerField(label="ID", read_only=True)
    pid = IntegerField(required=True, help_text="场所ID")
    tid = IntegerField(required=True, help_text="经营名目ID")
    trxdate = CharField(required=True, help_text="结算截止日期")
    creattime = DateTimeField(required=False, help_text="当前结算时间")
    acount = IntegerField(min_value=0, required=False, help_text="收单数")
    amoney = IntegerField(min_value=0, required=False, help_text="收单金额")
    afee = IntegerField(min_value=0, required=False, help_text="收单手续费")
    ocount = IntegerField(min_value=0, required=False, help_text="退单数")
    omoney = IntegerField(min_value=0, required=False, help_text="退单金额")
    ofee = IntegerField(min_value=0, required=False, help_text="退单手续费")
    myfee = IntegerField(min_value=0, required=False, help_text="平台手续费")
    is_vlid = IntegerField(min_value=0, default=0, help_text="核算审核")
    is_transfer = IntegerField(min_value=0, default=0, help_text="打款状态")

    class Meta:
        model = AllinpaySettlementList
        fields = "__all__"
        validators = [
            UniqueTogetherValidator(
                queryset=AllinpaySettlementList.objects.all(),
                fields=("pid", "tid", "trxdate"),
            )
        ]

    def validate_pid(self, attr):
        try:
            AllinpayPlaceList.objects.get(id=attr)
        except BaseException as err:
            if not attr == 0:
                raise serializers.ValidationError("场所对象不存在")
        return attr

    def validate_tid(self, attr):
        try:
            AllinpayTermList.objects.get(id=attr)
        except BaseException as err:
            raise serializers.ValidationError("场所对象不存在")
        return attr


class AllinpaySettlementVlidSerializer(serializers.ModelSerializer):
    """审核结算表记录"""

    id = IntegerField(label="ID", help_text="记录ID")
    is_vlid = IntegerField(min_value=0, default=0, help_text="核算审核")

    class Meta:
        model = AllinpaySettlementList
        fields = ("id", "is_vlid")

    def validate_id(self, attr):
        try:
            AllinpaySettlementList.objects.get(id=attr)
        except BaseException as err:
            raise serializers.ValidationError("结算记录不存在")
        return attr


class allinpaySettlementBankSerializer(serializers.ModelSerializer):
    """结算打款"""

    id = IntegerField(label="ID", read_only=True)
    reqsn = CharField(
        help_text="银行流水",
        validators=[UniqueValidator(queryset=AllinpaySettlementBank.objects.all())],
    )
    money = IntegerField(help_text="打款金额")
    bankname = CharField(help_text="收款银行")
    bankuser = CharField(help_text="户名")
    bankcard = CharField(help_text="卡号")
    uid = IntegerField(help_text="操作员ID")
    sid = IntegerField(required=False, help_text="结算记录ID")
    fintime = DateTimeField(default=timezone.now, help_text="打款时间")

    class Meta:
        model = AllinpaySettlementBank
        fields = "__all__"

    def validate_uid(self, attr):
        try:
            AllinpayUserList.objects.get(id=attr)
        except BaseException as err:
            raise serializers.ValidationError("用户对象不存在")
        return attr

    def validate_sid(self, attr):
        try:
            sess = AllinpaySettlementList.objects.get(id=attr)
            sess.is_transfer = 1
            sess.save()
        except BaseException as err:
            raise serializers.ValidationError("结算记录不存在")
        return attr

    def validate_fintime(self, attr):
        return timezone.now()


# print(repr(AllOrderSerializer()))
